<template>
  <div>
    <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片列表 -->
    <el-card>
      <el-row :gutter="25">
        <el-col :span="6">
          <!-- 搜索区域 搜索框 -->
          <el-input
            v-model="userInfo.query"
            placeholder="请输入内容"
            class="input-with-select"
            clearable
            @clear="getUserlist"
          >
            <el-button @click="getUserlist" slot="append" icon="el-icon-search"></el-button>
          </el-input>
        </el-col>
        <el-col :span="4">
          <el-button type="primary" @click="addDialogVisible = true">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 用户列表区域 -->
      <el-table :data="Userlist" stripe border width="100%">
        <el-table-column align="center" type="index" label="#"></el-table-column>
        <el-table-column align="center" prop="username" label="姓名"></el-table-column>
        <el-table-column align="center" prop="email" label="邮箱"></el-table-column>
        <el-table-column align="center" prop="mobile" label="电话"></el-table-column>
        <el-table-column align="center" prop="role_name" label="角色"></el-table-column>
        <el-table-column align="center" label="状态">
          <!-- 使用作用域插槽绑定状态值 row是vue底层封装的自定名 包含多种数据 作用域插槽会覆盖prop的值 所以可以去掉 -->
          <template slot-scope="scope">
            <el-switch v-model="scope.row.mg_state" @change="userStateChange(scope.row)"></el-switch>
          </template>
        </el-table-column>
        <el-table-column align="center" label="操作">
          <template slot-scope="scope">
            <el-button
              plain
              type="primary"
              size="mini"
              icon="el-icon-edit"
              @click="editHandleUser(scope.row.id)"
            ></el-button>
            <!-- 通过作用域插槽接收id -->
            <el-button
              plain
              type="danger"
              size="mini"
              icon="el-icon-delete"
              @click="removeUser(scope.row.id)"
            ></el-button>
            <el-tooltip effect="dark" content="分配角色" placement="top" :enterable="false">
              <el-button
                plain
                type="warning"
                size="mini"
                icon="el-icon-setting"
                @click="allowRole(scope.row)"
              ></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页区域 -->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="userInfo.pagenum"
        :page-sizes="[1, 2, 3, 4, 5, 6]"
        :page-size="userInfo.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>
    <!-- 添加一个添加用户的弹框 :visible.sync控制弹框的显示和隐藏 -->
    <el-dialog
      title="添加用户"
      :visible.sync="addDialogVisible"
      width="50%"
      center
      @close="closeAddDialog"
    >
      <!-- span是弹框的主体部分 -->
      <el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="80px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="addForm.password"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addForm.email"></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="addForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 弹框的底部按钮区域 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addUser">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 添加一个编辑弹框 -->
    <el-dialog title="编辑用户" :visible.sync="editDialogVisible" width="50%" @close="closeEditDialog">
      <!-- 输入框主体内容 -->
      <el-form ref="editFormRef" :model="editForm" :rules="editFormRules" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="editForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="editForm.email"></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="editForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editSave">修 改</el-button>
      </span>
    </el-dialog>

    <!-- 添加一个分配角色对话框 -->
    <el-dialog title="分配角色" :visible.sync="setRoleDialog" width="50%" @close="clearSelect">
      <div class="setRoles">
        <p>当前用户: {{queryInfo.username}}</p>
        <p>当前角色: {{queryInfo.role_name}}</p>
        <p>
          分配角色:
          <el-select v-model="selectRoleId" placeholder="请选择">
            <el-option
              v-for="item in roleList"
              :key="item.id"
              :label="item.roleName"
              :value="item.id"
            ></el-option>
          </el-select>
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRoleDialog = false">取 消</el-button>
        <el-button type="primary" @click="saveRoles">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data () {
    // 自定义邮箱规则 value是用户输入的值
    const checkEmail = (rule, value, callback) => {
      // 验证输入的值是否符合标准
      const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/
      if (regEmail.test(value)) {
        return callback()
      }
      callback(new Error('请输入正确的邮箱'))
    }
    // 自定义手机号码的正则
    const checkMobile = (rule, value, callback) => {
      const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/
      if (regMobile.test(value)) {
        return callback()
      }
      callback(new Error('请输入正确的手机号码'))
    }
    return {
      // 获取用户列表的参数
      userInfo: {
        query: '',
        pagenum: 1,
        pagesize: 1
      },
      // 定义一个新的数据列表数组接收后台的数据
      Userlist: [],
      total: 0, // 列表用户数据的总数
      addDialogVisible: false, // 定义弹框的默认值为false 是隐藏
      addForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      // 添加用户验证规则
      addFormRules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
        ],
        // 对密码进行验证
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 15, message: '密码错误，请输入正确的密码', trigger: 'blur' }
        ],
        // 对邮箱进行验证
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        // 对手机进行验证
        mobile: [
          { required: true, message: '请输入手机号码', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' }
        ]
      },
      // 定义编辑弹框的默认值
      editDialogVisible: false,
      // 定义一个空的编辑对象接收后台数据
      editForm: {},
      // 定义一个用户编辑的验证规则
      editFormRules: {
        // 对邮箱进行验证
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        // 对手机进行验证
        mobile: [
          { required: true, message: '请输入手机号码', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' }
        ]
      },
      queryInfo: {},
      // 定义接收添加角色数据数组
      roleList: [],

      // 定义对话框隐藏
      setRoleDialog: false,

      // 绑定值id
      selectRoleId: ''
    }
  },
  created () {
    // 在这里调用获取用户列表的渲染页面的自定义函数
    this.getUserlist()
  },
  methods: {
    // 定义获取用户列表数据的自定义函数
    async getUserlist () {
      // 利用axios异步请求 获取数据 promise异步请求
      const { data: res } = await this.$http.get('/users', { params: this.userInfo }) // 这里的get请求后面是一个对象 必须要用params
      // 判断是否获取成功 失败返回后台的数据提示 成功后将后台数据赋值给新定义的列表数组和总数
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.Userlist = res.data.users
      this.total = res.data.total
      // console.log(res)
    },

    // pageSize 改变时会触发 显示当前的页面条数 定义函数 handleSizeChange 点击之后改变每页的显示条数
    handleSizeChange (newPagesize) {
      this.userInfo.pagesize = newPagesize
      this.getUserlist()
    },

    // current-change currentPage 改变时会触发 显示当前页
    handleCurrentChange (newPagenum) {
      this.userInfo.pagenum = newPagenum
      this.getUserlist()
    },

    // change事件 监听switch 状态发生变化时的回调函数 定义一个userStateChange函数更改状态 userState接收传过来的值
    async userStateChange (userState) {
      // console.log(userState)
      const { data: res } = await this.$http.put(`/users/${userState.id}/state/${userState.mg_state}`)
      // 如果状态不等于200 就将当前更改的状态取反 并返回后台的提示数据
      if (res.meta.status !== 200) {
        userState.mg_state = !userState.mg_state
        return this.$message.error(res.meta.msg)
      }
      // 成功返回后台提示信息
      this.$message.success(res.meta.msg)
    },

    // 定义一个关闭弹框清空表单
    closeAddDialog () {
      this.$refs.addFormRef.resetFields()
    },

    // 点击确定添加用户 并在添加之前用validate对表单进行一个校验 成功之后再发送请求
    addUser () {
      this.$refs.addFormRef.validate(async valid => {
        // 表单校验
        if (!valid) return
        // 成功发送请求
        const { data: res } = await this.$http.post('/users', this.addForm)
        if (res.meta.status !== 201) return this.$message.error(res.meta.msg)
        this.$message.success(res.meta.msg)
        // 隐藏对话框
        this.addDialogVisible = false
        // 刷新列表
        this.getUserlist()
      })
    },

    // 点击编辑按钮触发一个事件 发送ajax请求获取后台数据 打开弹框
    async editHandleUser (id) {
      const { data: res } = await this.$http.get(`/users/${id}`)
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.editForm = res.data
      // console.log(res)
      // 打开弹框
      this.editDialogVisible = true
    },

    // 在Dialog标签添加一个close事件 定义一个重置编辑表单closeEditDialog函数 退出后清空表单
    closeEditDialog () {
      this.$refs.editFormRef.resetFields()
    },

    // 修改表单之前进行一个预校验
    editSave () {
      this.$refs.editFormRef.validate(async valid => {
        // console.log(valid)
        // 校验不成功就return
        if (!valid) return
        // 成功之后利用axios的异步请求获取后台数据 async 和 await方式
        const { data: res } = await this.$http.put(`/users/${this.editForm.id}`, {
          email: this.editForm.email,
          mobile: this.editForm.mobile
        })
        // 如果status不等于200 弹出错误提示
        if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
        // 成功之后将数据刷新
        this.getUserlist()
        // 给出成功的提示
        this.$message.success(res.meta.msg)
        // 退出弹出框
        this.editDialogVisible = false
      })
    },

    // 定义一个删除用户名的函数方法
    async removeUser (id) {
      // console.log(id) this.$confirm是一个promise对象 可以使用async 和 await
      const confirmResult = await this.$confirm('此用户名将永久删除, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      // confirmResult 返回值是confirm 表示同意删除
      // confirmResult 返回值是cancle 表示取消删除
      if (confirmResult !== 'confirm') {
        return this.$message.error('您取消了本次操作')
      }
      // 执行删除操作
      const { data: res } = await this.$http.delete(`/users/${id}`)
      // 如果状态是"status": 200 表示删除成功
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // 成功之后
      this.$message.success(res.meta.msg)
      // 刷新页面
      this.getUserlist()
      // console.log(confirmResult)
    },

    // 获取列表数据
    async allowRole (queryInfo) {
      this.queryInfo = queryInfo
      const { data: res } = await this.$http.get('/roles')
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // console.log(res)
      this.roleList = res.data
      this.setRoleDialog = true
    },

    // 点击确定按钮 完成分配功能
    async saveRoles () {
      // 先判断id是否存在
      if (!this.selectRoleId) return this.$message.error('请选择要分配的角色')
      const { data: res } = await this.$http.put(`/users/${this.queryInfo.id}/role`, { rid: this.selectRoleId })
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.$message.success(res.meta.msg)
      this.getUserlist()
      this.setRoleDialog = false
    },

    // 清空选择
    clearSelect () {
      this.selectRoleId = ''
      this.queryInfo = {}
    }
  }
}
</script>

<style lang="less" scoped>
.setRoles p {
  margin: 15px 0px 0px 20px;
}
</style>
